package GUI;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;

import queenProblem.PlayField;
import queenProblem.QueenProblemSolver;

/**
 * Class responsible for the GUI of the Queen Problem
 *
 */
@SuppressWarnings("serial")
public class StartWindow extends JFrame {
	
	// Initialize the QueenProblemSolver
	QueenProblemSolver sim;
	
	// Initialize the Graphics components
	boolean[][] playField;

	// Initialize the chess board components 
	private JPanel buttonPanel;
	private JButton[][] gameField;
	
	// Initialize the simulation control components
	private JPanel simulationControlPanel;
	JLabel boardSizeEntryTextLabel;
	private JTextField boardSizeEntry;
	// Set the default board size
	private int fieldSize=10;
	private JButton generateFieldButton;
	private JLabel delayTextLabel;
	private JTextField delayText;
	Icon q = new ImageIcon(getClass().getResource("queen.jpg"));
	JButton solveButton;
	
	/**
	 * Constructor for the GUI
	 */
	public StartWindow(){
		// First, name the window
		super("Start");
		
		// Initialize and display the simulation control panel
		this.initializeSimulationControl();
      
      // Finally, allow the window to close properly
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
	}
	
	/**
	 * Initializes and displays the simulation control portion of the main window
	 */
	private void initializeSimulationControl() {
		simulationControlPanel = new JPanel();
		simulationControlPanel.setLayout(new FlowLayout());
		// Initialize the board size (number of queens) text field and prepare it for user input
		boardSizeEntryTextLabel = new JLabel("Count of Queens:");
		boardSizeEntry = new JTextField(5);
		boardSizeEntry.addActionListener(new ActionListener (){
			@Override
			public void actionPerformed(ActionEvent arg0) {
				fieldSize= Integer.valueOf(boardSizeEntry.getText()).intValue();
			}
		});
		// Initialize the generate button and prepare it to generate the chess board
		generateFieldButton = new JButton("Generate");
		generateFieldButton.addActionListener(new ActionListener (){
			@Override
			public void actionPerformed(ActionEvent arg0) {
				generateChessBoard();
			}
		});
		// Initialize the delay text-entry field and prepare it for user input
		delayTextLabel = new JLabel("Delay:");
		delayText = new JTextField(7);
		delayText.setEditable(true);
		delayText.addActionListener(new ActionListener (){
			@Override
			public void actionPerformed(ActionEvent arg0) {
				Integer.valueOf(delayText.getText()).intValue();
			}
		});
		// Initialize the solve button and prepare it for user input		
		solveButton = new JButton("Solve it!");
		solveButton.addActionListener( new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e) {
				solve();
			}
		});
		// Finalize the components and add them to the simulation control panel
		simulationControlPanel.add(solveButton);
		simulationControlPanel.add(boardSizeEntryTextLabel);
		simulationControlPanel.add(boardSizeEntry);
		simulationControlPanel.add(delayTextLabel);
		simulationControlPanel.add(delayText);
		simulationControlPanel.add(generateFieldButton);
		// Add the simulation control panel to the window
		add(simulationControlPanel,BorderLayout.SOUTH);
		
	}

	/**
	 * Instructs the main class to solve the current queen situation
	 */
	protected void solve() {

		if (delayText.getText().equals("")){
			JOptionPane.showMessageDialog(null, "Please enter a delay!", "No Delay Entered!", JOptionPane.ERROR_MESSAGE);
		} else{
			generateFieldButton.setEnabled(false);
			solveButton.setEnabled(false);
			for(JButton[] column : gameField){
				for(JButton space : column){
					space.setEnabled(false);
				}
			}
			sim = new QueenProblemSolver(playField, Integer.valueOf(delayText.getText()).intValue(), this);
			firePropertyChange("solve", null, "solve");
		}
		
		
	}

	/**
	 * Generates the field of buttons that represent the chess board
	 */
	private void generateChessBoard() {
		if (buttonPanel != null){
			this.remove(buttonPanel);
		}
		if (Integer.valueOf(boardSizeEntry.getText()) < 1){
			JOptionPane.showMessageDialog(null, "Illegal Field Size! Please change the number of Queens!", "Illegal Field Size!", JOptionPane.ERROR_MESSAGE);
		} else {
			fieldSize= Integer.valueOf(boardSizeEntry.getText()).intValue();
			playField = new boolean[fieldSize][fieldSize];
			buttonPanel= new JPanel();
			buttonPanel.setLayout(new GridLayout(fieldSize,fieldSize));
			gameField = new JButton[fieldSize][fieldSize];
		    for(int row = 0; row < fieldSize; row++){
			   for(int column= 0; column< fieldSize; column++){
				   gameField[row][column] = newChessFieldButton(row, column);
				   buttonPanel.add(gameField[row][column]);
			   }
		    }
		    add(buttonPanel,BorderLayout.CENTER);
		    JOptionPane.showMessageDialog(null, "Generated!");
		    buttonPanel.updateUI();
		}
		
	}
	
	/**
	 * Creates a JButton to be used as a space on the chess board
	 * @param row is the y coordinate of the space
	 * @param column is the x coordinate of the space
	 * @return a JButton to be used as a space on the chess board
	 */
	private JButton newChessFieldButton(int row, int column) {
		final JButton newButton = new JButton();
		newButton.setEnabled(true);
		newButton.setText("");
		newButton.setBackground(getColor(row, column));
		newButton.setForeground(new Color(0, 0, 250));
		final int otherRow = row;
		final int otherColumn = column;
		newButton.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent arg0) {
				
				if((! playField[otherRow][otherColumn]) && QueenProblemSolver.isQueenSettable(otherRow, otherColumn, new PlayField(playField))){
					setQueen(otherRow,otherColumn);
				}else if(playField[otherRow][otherColumn]){
					removeQueen(otherRow,otherColumn);
				}else {
					JOptionPane.showMessageDialog(null, "You cannot set a Queen there!");
				}
			
				}
			
		});
		return newButton;
	}

	/**
	 * Removes a queen from the GUI at a given position
	 * @param row is the y position of the queen to be removed
	 * @param column is the x position of the queen to be removed
	 */
	public void removeQueen(int row, int column) {
		gameField[row][column].removeAll();
		gameField[row][column].validate();
		playField[row][column] = false;
		buttonPanel.updateUI();
		
	}

	/**
	 * Sets a queen in the GUI at a given position
	 * @param row is the y position of the queen to be set
	 * @param column is the x position of the queen to be set
	 */
	public void setQueen(int row, int column) {
		gameField[row][column].add(new JLabel(q),BorderLayout.CENTER);
		playField[row][column] = true;
		buttonPanel.updateUI();
		
	}

	/**
	 * Returns the color of the space on a chess board, determined by its x and y positions
	 * @param row is the y position of the space
	 * @param column is the x position of the space
	 * @return a Color object representing the color of the space
	 */
	private static Color getColor(int row, int column){
		if((row+column) % 2 == 0)
			return new Color(255, 255, 255);
		else
			return new Color(0, 0, 0);
	}

	/**
	 * Displays a message indicating if the puzzle was solved or not
	 * @param result is a boolean indicating if the puzzle was solved or not
	 */
	public void displaySolveResult(boolean result) {
		String resultMessage;
		if (result){
			resultMessage = "Problem Solved!";
		} else {
			resultMessage = "Problem is not solvable!";
		}
		JOptionPane.showMessageDialog(null, resultMessage);
		generateFieldButton.setEnabled(true);
		solveButton.setEnabled(true);
		/*
		for(JButton[] column : gameField){
			for(JButton space : column){
				space.setEnabled(true);
			}
		}
		*/
	}

	/**
	 * Displays a message indicating the input delay was too small and the default delay was used
	 */
	public void displayDelayError() {
		JOptionPane.showMessageDialog(null, "Delay too small; default delay (100 ms) used instead.", "Error: Delay", JOptionPane.ERROR_MESSAGE);		
	}
	
}
